#ifdef WINDOWS

#include "selftest_local.h"

void Test_Expressions_RunTests_Basic() {
	// reset whole device
	SIM_ClearOBK(0);

	// parser must be able to both handle '-' as an operation and '-' as a negative sign before number
	SELFTEST_ASSERT(Float_Equals(CMD_EvaluateExpression("-1",0), -1.0f));
	SELFTEST_ASSERT(Float_Equals(CMD_EvaluateExpression("-11", 0), -11.0f));

	SELFTEST_ASSERT_EXPRESSION("-1-1", -2);
	SELFTEST_ASSERT_EXPRESSION("1-1", 0);
	SELFTEST_ASSERT_EXPRESSION("1+1", 2);
	SELFTEST_ASSERT_EXPRESSION("-1.0-1.0", -2);
	// same as above but with spaces
	SELFTEST_ASSERT_EXPRESSION("-1 -1", -2);
	SELFTEST_ASSERT_EXPRESSION("1 - 1", 0);
	SELFTEST_ASSERT_EXPRESSION("1 + 1", 2);
	SELFTEST_ASSERT_EXPRESSION(" 1 + 1 ", 2);
	SELFTEST_ASSERT_EXPRESSION("-1.0 -1.0", -2);
	SELFTEST_ASSERT_EXPRESSION("-1.0 - 1.0", -2);
	// multiply
	SELFTEST_ASSERT_EXPRESSION("5*10", 50);
	SELFTEST_ASSERT_EXPRESSION("10*5", 50);
	SELFTEST_ASSERT_EXPRESSION("10*0.5", 5);
	SELFTEST_ASSERT_EXPRESSION("0.5*10", 5);
	SELFTEST_ASSERT_EXPRESSION("0.5*0.5", 0.25);
	// same as above but with spaces
	SELFTEST_ASSERT_EXPRESSION("5*  10", 50);
	SELFTEST_ASSERT_EXPRESSION("10  *5", 50);
	SELFTEST_ASSERT_EXPRESSION("10  *0.5", 5);
	SELFTEST_ASSERT_EXPRESSION("0.5   *   10", 5);
	SELFTEST_ASSERT_EXPRESSION("   0.5  *  0.5  ", 0.25);
	// test spaces
	SELFTEST_ASSERT_EXPRESSION("10.0", 10.0f);
	SELFTEST_ASSERT_EXPRESSION("  10.0   ", 10.0f);
	SELFTEST_ASSERT_EXPRESSION("  10.0*2   ", 20.0f);
	SELFTEST_ASSERT_EXPRESSION("  10.0*2.4   ", 24.0f);
	SELFTEST_ASSERT_EXPRESSION("  10.0+2.4   ", 12.40f);
	SELFTEST_ASSERT_EXPRESSION("  10.0+ 3.4   ", 13.40f);
	SELFTEST_ASSERT_EXPRESSION("  10.0 + 4.4   ", 14.40f);
	CHANNEL_Set(12, 10, 0);

	SELFTEST_ASSERT_EXPRESSION("$CH12*10.0", 100.0f);
	SELFTEST_ASSERT_EXPRESSION("$CH12+10.0", 20.0f);
	SELFTEST_ASSERT_EXPRESSION("10.0+$CH12", 20.0f);
	SELFTEST_ASSERT_EXPRESSION("10.0+$CH12 \r\n", 20.0f);
	SELFTEST_ASSERT_EXPRESSION("10.0+$CH12\n\r", 20.0f);

	// same as above but channel 1 instead of 12 and value 1 instead of 10
	CHANNEL_Set(1, 1, 0);
	SELFTEST_ASSERT_EXPRESSION("$CH1*10.0", 10.0f);
	SELFTEST_ASSERT_EXPRESSION("$CH1+10.0", 11.0f);
	SELFTEST_ASSERT_EXPRESSION("10.0+$CH1", 11.0f);
	SELFTEST_ASSERT_EXPRESSION("10.0+$CH1 \r\n", 11.0f);
	SELFTEST_ASSERT_EXPRESSION("10.0+$CH1\n\r", 11.0f);

	CHANNEL_Set(18, 15, 0);
	SELFTEST_ASSERT_EXPRESSION("15.0+$CH18\n\r", 30.0f);
	SELFTEST_ASSERT_EXPRESSION("15.0/$CH18\n\r", 1.0f);
	SELFTEST_ASSERT_EXPRESSION("1.50/$CH18\n\r", 0.1f);

	// Logical operators
	// &&
	SELFTEST_ASSERT_EXPRESSION("1&&1\n\r", 1.0f);
	SELFTEST_ASSERT_EXPRESSION("1&&0\n\r", 0.0f);
	SELFTEST_ASSERT_EXPRESSION("0&&0\n\r", 0.0f);
	SELFTEST_ASSERT_EXPRESSION("0&&1\n\r", 0.0f);
	// ||
	SELFTEST_ASSERT_EXPRESSION("1||1\n\r", 1.0f);
	SELFTEST_ASSERT_EXPRESSION("1||0\n\r", 1.0f);
	SELFTEST_ASSERT_EXPRESSION("0||0\n\r", 0.0f);
	SELFTEST_ASSERT_EXPRESSION("0||1\n\r", 1.0f);
	// Channel 1 is 1, it was set to 1 above
	// &&
	SELFTEST_ASSERT_EXPRESSION("$CH1&&$CH1\n\r", 1.0f);
	SELFTEST_ASSERT_EXPRESSION("$CH1&&0\n\r", 0.0f);
	SELFTEST_ASSERT_EXPRESSION("0&&0\n\r", 0.0f);
	SELFTEST_ASSERT_EXPRESSION("0&&$CH1\n\r", 0.0f);
	// ||
	SELFTEST_ASSERT_EXPRESSION("$CH1||$CH1\n\r", 1.0f);
	SELFTEST_ASSERT_EXPRESSION("$CH1||0\n\r", 1.0f);
	SELFTEST_ASSERT_EXPRESSION("0||0\n\r", 0.0f);
	SELFTEST_ASSERT_EXPRESSION("0||$CH1\n\r", 1.0f);
	// set $CH1 to 0
	CHANNEL_Set(1, 0, 0);
	// &&
	SELFTEST_ASSERT_EXPRESSION("1&&1\n\r", 1.0f);
	SELFTEST_ASSERT_EXPRESSION("1&&$CH1\n\r", 0.0f);
	SELFTEST_ASSERT_EXPRESSION("$CH1&&$CH1\n\r", 0.0f);
	SELFTEST_ASSERT_EXPRESSION("$CH1&&1\n\r", 0.0f);
	// ||
	SELFTEST_ASSERT_EXPRESSION("1||1\n\r", 1.0f);
	SELFTEST_ASSERT_EXPRESSION("1||$CH1\n\r", 1.0f);
	SELFTEST_ASSERT_EXPRESSION("$CH1||$CH1\n\r", 0.0f);
	SELFTEST_ASSERT_EXPRESSION("$CH1||1\n\r", 1.0f);

	// Logical operators
	// !
	SELFTEST_ASSERT_EXPRESSION("!0\n\r", 1.0f);
	SELFTEST_ASSERT_EXPRESSION("!1\n\r", 0.0f);
	// set $CH1 to 0
	CHANNEL_Set(1, 0, 0);
	SELFTEST_ASSERT_EXPRESSION("!$CH1\n\r", 1.0f);
	SELFTEST_ASSERT_EXPRESSION("$CH1\n\r", 0.0f);
	// set $CH1 to 1
	CHANNEL_Set(1, 1, 0);
	SELFTEST_ASSERT_EXPRESSION("!$CH1\n\r", 0.0f);
	SELFTEST_ASSERT_EXPRESSION("$CH1\n\r", 1.0f);

	// order of operations
	SELFTEST_ASSERT_EXPRESSION("1+1*2", 3);
	SELFTEST_ASSERT_EXPRESSION("1*2+1", 3);
	SELFTEST_ASSERT_EXPRESSION("100+1*2", 102);
	SELFTEST_ASSERT_EXPRESSION("100*2+1", 201);
	SELFTEST_ASSERT_EXPRESSION("100*2+10*2+2*1", 222);
	SELFTEST_ASSERT_EXPRESSION("100*2-10*2+2*1", 182);
	SELFTEST_ASSERT_EXPRESSION("10*10/10", 10);

	SELFTEST_ASSERT_EXPRESSION("1000*2+100*2+10*2+2*1", 2222);
	SELFTEST_ASSERT_EXPRESSION("1000*2+100*2-10*2+2*1", 2182);
	SELFTEST_ASSERT_EXPRESSION("1000*2-100*2-10*2+2*1", 1782);

	// set $CH1 to 2
	CHANNEL_Set(1, 2, 0);
	SELFTEST_ASSERT_EXPRESSION("1000*$CH1+100*$CH1+10*$CH1+$CH1*1", 2222);
	SELFTEST_ASSERT_EXPRESSION("1000*$CH1+100*$CH1-10*$CH1+$CH1*1", 2182);
	SELFTEST_ASSERT_EXPRESSION("1000*$CH1-100*$CH1-10*$CH1+$CH1*1", 1782);

	SELFTEST_ASSERT_EXPRESSION("1 > 2", 0);
	SELFTEST_ASSERT_EXPRESSION("1 > 3", 0);
	SELFTEST_ASSERT_EXPRESSION("1 > 1", 0);
	SELFTEST_ASSERT_EXPRESSION("1 > 0", 1);
	SELFTEST_ASSERT_EXPRESSION("1 > -1", 1);

	SELFTEST_ASSERT_EXPRESSION("1 >= 2", 0);
	SELFTEST_ASSERT_EXPRESSION("1 >= 3", 0);
	SELFTEST_ASSERT_EXPRESSION("1 >= 1", 1);
	SELFTEST_ASSERT_EXPRESSION("1 >= 0", 1);
	SELFTEST_ASSERT_EXPRESSION("1 >= -1", 1);

	SELFTEST_ASSERT_EXPRESSION("1 <= 2", 1);
	SELFTEST_ASSERT_EXPRESSION("1 <= 3", 1);
	SELFTEST_ASSERT_EXPRESSION("1 <= 1", 1);
	SELFTEST_ASSERT_EXPRESSION("1 <= 0", 0);
	SELFTEST_ASSERT_EXPRESSION("1 <= -1", 0);

	// set channel 5 to 1
	CHANNEL_Set(5, 1, 0);
	SELFTEST_ASSERT_EXPRESSION("$CH5 > 2", 0);
	SELFTEST_ASSERT_EXPRESSION("$CH5 > 3", 0);
	SELFTEST_ASSERT_EXPRESSION("$CH5 > $CH5", 0);
	SELFTEST_ASSERT_EXPRESSION("$CH5 > 0", 1);
	SELFTEST_ASSERT_EXPRESSION("$CH5 > -1", 1);

	SELFTEST_ASSERT_EXPRESSION("$CH5 >= 2", 0);
	SELFTEST_ASSERT_EXPRESSION("$CH5 >= 3", 0);
	SELFTEST_ASSERT_EXPRESSION("$CH5 >= 1", 1);
	SELFTEST_ASSERT_EXPRESSION("$CH5 >= 0", 1);
	SELFTEST_ASSERT_EXPRESSION("$CH5 >= -1", 1);

	SELFTEST_ASSERT_EXPRESSION("$CH5 <= 2", 1);
	SELFTEST_ASSERT_EXPRESSION("$CH5 <= 3", 1);
	SELFTEST_ASSERT_EXPRESSION("$CH5 <= 1", 1);
	SELFTEST_ASSERT_EXPRESSION("$CH5 <= 0", 0);
	SELFTEST_ASSERT_EXPRESSION("$CH5 <= -1", 0);

	SELFTEST_ASSERT_EXPRESSION("1 > -1 && 5 > 4", 1);
	SELFTEST_ASSERT((1 > -1 && 5 > 4) == 1);

	SELFTEST_ASSERT_EXPRESSION("1 >= -1 && 5 >= 4", 1);
	SELFTEST_ASSERT((1 >= -1 && 5 >= 4) == 1);

	SELFTEST_ASSERT_EXPRESSION("1 >= -1 && 5 >= 5", 1);
	SELFTEST_ASSERT((1 >= -1 && 5 >= 5) == 1);

	SELFTEST_ASSERT_EXPRESSION("1 >= -1 && 5 >= 6", 0);
	SELFTEST_ASSERT((1 >= -1 && 5 >= 6) == 0);

	SELFTEST_ASSERT_EXPRESSION("-1+2 >= -1 && 5 >= 6", 0);
	SELFTEST_ASSERT((-1+2 >= -1 && 5 >= 6) == 0);

	SELFTEST_ASSERT_EXPRESSION("1 >= -1 && 5 >= 7", 0);
	SELFTEST_ASSERT((1 >= -1 && 5 >= 7) == 0);

	SELFTEST_ASSERT_EXPRESSION("1 >= 0 && 5 >= 7", 0);
	SELFTEST_ASSERT((1 >= 0 && 5 >= 7) == 0);

	SELFTEST_ASSERT_EXPRESSION("1 >= 0 || 5 >= 7", 1);
	SELFTEST_ASSERT((1 >= 0 || 5 >= 7) == 1);

	SELFTEST_ASSERT_EXPRESSION("-1+2 >= 0 || 5 >= 7", 1);
	SELFTEST_ASSERT((-1 + 2 >= 0 || 5 >= 7) == 1);

	SELFTEST_ASSERT_EXPRESSION("-1+2 >= 0 || 5 >= 3+4", 1);
	SELFTEST_ASSERT((-1 + 2 >= 0 || 5 >= 3 + 4) == 1);

	SELFTEST_ASSERT_EXPRESSION("-1+2 >= 10-10 || 5 >= 3+4", 1);
	SELFTEST_ASSERT((-1 + 2 >= 10-10 || 5 >= 3 + 4) == 1);

	// some incorrect expression to check if we at least don't have a crash
	SELFTEST_ASSERT_EXPRESSION("+++++", 0);
	SELFTEST_ASSERT_EXPRESSION("++--++", 0);
	SELFTEST_ASSERT_EXPRESSION("++fsfs+", 0);

	SELFTEST_ASSERT_EXPRESSION("1000*2+100*2+10*2+2*1", 2222);
	SELFTEST_ASSERT_EXPRESSION("1000*2+100*2-10*2+2*1", 2182);
	SELFTEST_ASSERT_EXPRESSION("1000*2-100*2-10*2+2*1", 1782);

	// set $CH1 to 2
	CHANNEL_Set(1, 2, 0);
	SELFTEST_ASSERT_EXPRESSION("1000*$CH1+100*$CH1+10*$CH1+$CH1*1", 2222);
	SELFTEST_ASSERT_EXPRESSION("1000*$CH1+100*$CH1-10*$CH1+$CH1*1", 2182);
	SELFTEST_ASSERT_EXPRESSION("1000*$CH1-100*$CH1-10*$CH1+$CH1*1", 1782);

	SELFTEST_ASSERT_EXPRESSION("1 > 2", 0);
	SELFTEST_ASSERT_EXPRESSION("1 > 3", 0);
	SELFTEST_ASSERT_EXPRESSION("1 > 1", 0);
	SELFTEST_ASSERT_EXPRESSION("1 > 0", 1);
	SELFTEST_ASSERT_EXPRESSION("1 > -1", 1);

	SELFTEST_ASSERT_EXPRESSION("1 >= 2", 0);
	SELFTEST_ASSERT_EXPRESSION("1 >= 3", 0);
	SELFTEST_ASSERT_EXPRESSION("1 >= 1", 1);
	SELFTEST_ASSERT_EXPRESSION("1 >= 0", 1);
	SELFTEST_ASSERT_EXPRESSION("1 >= -1", 1);

	SELFTEST_ASSERT_EXPRESSION("1 <= 2", 1);
	SELFTEST_ASSERT_EXPRESSION("1 <= 3", 1);
	SELFTEST_ASSERT_EXPRESSION("1 <= 1", 1);
	SELFTEST_ASSERT_EXPRESSION("1 <= 0", 0);
	SELFTEST_ASSERT_EXPRESSION("1 <= -1", 0);

	// modulo
	SELFTEST_ASSERT_EXPRESSION("5 % 2", 1);
	SELFTEST_ASSERT_EXPRESSION("5 % 3", 2);
	SELFTEST_ASSERT_EXPRESSION("5 % 5", 0);

	SELFTEST_ASSERT((1 + 3 % 2) == 2);
	SELFTEST_ASSERT_EXPRESSION("1 + 3 % 2", 2)

	SELFTEST_ASSERT((5 + 3 % 2) == 6);
	SELFTEST_ASSERT_EXPRESSION("5 + 3 % 2", 6)

	SELFTEST_ASSERT((6 + 3 % 2) == 7);
	SELFTEST_ASSERT_EXPRESSION("6 + 3 % 2", 7)

	SELFTEST_ASSERT((6 % 3 + 2) == 2);
	SELFTEST_ASSERT_EXPRESSION("6 % 3 + 2", 2)

	SELFTEST_ASSERT((3 - 6 % 3 + 2) == 5);
	SELFTEST_ASSERT_EXPRESSION("3 - 6 % 3 + 2", 5)

	SELFTEST_ASSERT((3 - 6 % 4 + 2) == 3);
	SELFTEST_ASSERT_EXPRESSION("3 - 6 % 4 + 2", 3)

	//CHANNEL_Set(18, 15, 0);
	//SELFTEST_ASSERT_EXPRESSION("15.0+$CH18+1000\n\r", 30.0f + 1000);
	//SELFTEST_ASSERT_EXPRESSION("15.0/$CH18+1000\n\r", 1.0f + 1000);
	//SELFTEST_ASSERT_EXPRESSION("1.50/$CH18+1000\n\r", 0.1f + 1000);
}

#endif
